package org.huangxq.bigscreen.service

import com.zaxxer.hikari.HikariDataSource
import org.huangxq.bigscreen.data.DataBaseData
import org.huangxq.bigscreen.repository.DataBaseRepository
import org.slf4j.LoggerFactory
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Service

@Service
class DataBaseService(val dataBaseRepository: DataBaseRepository) {

    private val log = LoggerFactory.getLogger("log")

    private val jdbcMap = mutableMapOf<String, JdbcTemplate>()

    private fun createDBPool(db: DataBaseData): HikariDataSource {
        val dbPool = HikariDataSource()
        when(db.type){
            "Oracle" -> {
                dbPool.driverClassName = "oracle.jdbc.driver.OracleDriver"
                dbPool.jdbcUrl = "jdbc:oracle:thin:@${db.ip}:${db.port}/${db.serv}"
                dbPool.poolName = db.name
            }
            "MySQL" -> {
                dbPool.driverClassName = "com.mysql.cj.jdbc.Driver"
                dbPool.jdbcUrl = "jdbc:mysql://${db.ip}:${db.port}/${db.serv}?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT"
                dbPool.poolName = db.name
            }
            "SQLServer" -> {
                dbPool.driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
                dbPool.jdbcUrl = "jdbc:sqlserver://${db.ip}:${db.port};DatabaseName=${db.serv}"
                dbPool.poolName = db.name
            }
        }
        dbPool.username = db.user
        dbPool.password = db.pass
        dbPool.idleTimeout = 5 * 60 * 1000
        dbPool.connectionTimeout = 3 * 60 * 1000
        dbPool.minimumIdle = 30
        dbPool.maximumPoolSize = 100
        return dbPool
    }

    fun getJDBC(id: String): JdbcTemplate?{
        var jdbc = jdbcMap[id]
        if(jdbc == null){
            jdbc = JdbcTemplate(createDBPool(getOne(id)))
            jdbcMap[id] = jdbc
        }
        return jdbc
    }

    fun save(dataBase: DataBaseData) {
        dataBaseRepository.save(dataBase)
        jdbcMap[dataBase.id]?.let {
            it.dataSource?.connection?.close()
            jdbcMap.remove(dataBase.id)
        }
    }

    fun delete(id: String) = dataBaseRepository.deleteById(id)

    fun getOne(id: String) = dataBaseRepository.findById(id).get()

    fun list(): List<DataBaseData> = dataBaseRepository.findAll()

    fun test(dataBase: DataBaseData) {
        val testDB = createDBPool(dataBase)
        try {
            testDB.connection
        }catch (e: Exception){
            log.error(e.toString())
            throw e
        }finally {
            testDB.close()
        }
    }
}